/* 
   PROGRAM USING DOUBLE HASHING METHOD OF OPEN ADDRESSING. 
   TEXT FILE USED IS "userpass.txt" .
   DATA of userpass.txt is ------
   
	USERID-sumit09046@iiitd.ac.in PASSWORD-12345678
	USERID-dude_buster@gmail.com PASSWORD-dhantenan
	USERID-gupta@hotmail.com PASSWORD-workontime
	USERID-lovely_sister@gmail.com PASSWORD-iamthebest
	USERID-great_itians@gmail.com PASSWORD-computers
	USERID-sumit91@yahoo.in PASSWORD-supersaiyan
	USERID-blahblahblah@gmail.com PASSWORD-blahblah
	USERID-metulsitereanganki@yahoo.in PASSWORD-serial
	USERID-zack_attack@gmail.com PASSWORD-098765
	USERID-weareone@gmail.com PASSWORD-nexus
	USERID-idli_sambar_vada@gmail.com PASSWORD-burp
	USERID-wikipedia@gmail.com PASSWORD-dictionary
	USERID-unluckynumber@gmail.com PASSWORD-itis13

   alpha(load factor) of this program is (Number of User-id in file/HASHSIZE) = 13/64 < 1.
   
   DESCRIPTION :
	Here I have used 3 different hash functions calculating the alpha value < 1. Each hash function re-initialize the same hash table wwith 	the data of userpass.txt. If we enter :
		wrong id - another try.
		wrong password - another try.
		3 times wrong input - access forbidden.
		correct id and password - Next hash function / output(in case of hash function 3) ends..
*/

#include<string.h>
#include<stdio.h>
#include<stdlib.h>

#define HASHSIZE 64						//size of hashtable
#define MAXLINE 320						//size of strings : user-id and password

int choice=1;							//to run loop for 3 hash functions

typedef struct tnode
{
 char *user;
 struct tnode *next;
}node;

void htable_init(node *hashtable);                            // initialize hashtable
void htable_insert(node *hashtable, char *str1, char *str2);  // insert data in hashtable
void htable_display(node *hashtable);                         // display hashtable
int htable_hash(node *hashtable,char *str);		      // hash data for hashtable
int htable_search(node *hashtable,char *str);         	      // search data from hashtable
int compare(char *s,char *p)
{
 int i,len1=0,len2=0;
 len1=strlen(s);
 len2=strlen(p)-1;
 if(len1!=len2)
   return (-1);
 else
 {
  for(i=0;s[i]==p[i];i++)
  { 
    if(i==len1-1)
     return 0;
  }
 }
 return (-1);
}

void *__gxx_personality_v0;				//part of exception handling.				

int main()
{
 char line1[MAXLINE],line2[MAXLINE];
 node *hashtable,*target;
 int i,c,j;
 FILE *fp;

 char checkstr[MAXLINE];
 int index;
 node *tmp;

 hashtable = (node*)malloc(HASHSIZE*sizeof(node));
 while(choice<4)
 {
  printf("\n@@@---For HASH FUNCTION %d.---@@@\n",choice);
  htable_init(hashtable);

  printf("\n------------------------\n");

  fp=fopen("userpass.txt","r");
  if(fp==NULL)
  {
    printf("\nCant open file.\n");
  }
  else
    printf("\nFile Opened.");

  c=getc(fp);
  while(c!=EOF)
  { 
    strcpy(line1,"");
    strcpy(line2,"");
    for(i=0;i<6;i++)
      c=getc(fp); 

    //storing userid
    c=getc(fp);  //first character of userid
    j=0;
    while(c!=' ')
    {
      line1[j]=c;
      j++;
      c=getc(fp);
    }
    line1[j]='\0'; 		//adding NULL character

    c=getc(fp);    //now c='P'
    for(i=0;i<9;i++)
      c=getc(fp); 

    //storing password
    j=0;
    while(c!='\n')
    {
      line2[j]=c;
      j++;
      c=getc(fp);
    }
    line2[j]='\0';

    htable_insert(hashtable,line1,line2);
    c=getc(fp);		//next U of USERID-
  }

  htable_display(hashtable);
 
 
  //allowing user to enter userid

  printf("\n------------------------\n");
  for(i=0;i<4;i++)
  {
   if(i==3)
   {
     printf("\n**--ERROR: TOO MANY TRIES. ACCESS FORBIDDEN.--**\n");
     break;
   }
   printf("\nTRY %d --------",i+1);
   printf("\nEnter User-id : ");
   char* user_id=(char*)malloc(100*sizeof(char));
   scanf("%99s",user_id);
   index=0;
   index=htable_search(hashtable,user_id);
   if(index==(-1))
     printf("**--ERROR: NO SUCH USER-ID.--**\n");
   else
   {
     printf("Enter Password : ");
     char* password=(char*)malloc(100*sizeof(char));
     scanf("%99s",password);
         
     target=hashtable+index;
     target=target->next;
     
     int res=compare(password,target->user); 
        
     if(res==0)			            
     { 
       printf("\n**--SUCCESS: PASSWORD MATCHED.--**\n");
       printf("\n");
       break;
     }
     else
     {
       printf("\n**--ERROR: WRONG PASSWORD.--**\n");
     }
   }
  }
 choice++;
 }
 return(0);
}

// initialize hashtable
void htable_init(node *hashtable)
{
 int i;
 for(i=0;i<HASHSIZE;i++)
 {
   hashtable[i].user=NULL;
   hashtable[i].next=NULL;
 }
}

// insert data in hashtable
void htable_insert(node *hashtable, char *str1,char *str2)
{
 int index=0;
 node *tmp;

 // determine hash function
 index = htable_hash(hashtable,str1);
 if(hashtable[index].user != NULL)
 {
  printf("\nCollission. Hash Table full.");
 }
 else
 {
  hashtable[index].user = (char*)calloc(strlen(str1)+1,sizeof(char));
  strcpy(hashtable[index].user,str1);
  
  tmp = hashtable + index;
  tmp->next = (node *)malloc(sizeof(node));  
  tmp->next->user = (char*)calloc(strlen(str2) + 1, sizeof(char));
  strcpy(tmp->next->user, str2);
  tmp->next->next = NULL;
 }
}

// hash data for hashtable
int htable_hash(node *hashtable,char *str)
{
 int index=0,index1=0,index2=0,i=0;
 char *tmp=NULL;

 tmp=(char*)calloc(strlen(str)+1,sizeof(char));
 strcpy(tmp,str);

 while(*tmp)
 {
  index+=*tmp;
  tmp++;
 }
				//diffrent hash functions used
 index1=(index % HASHSIZE);
 if(choice==1)
   index2=(index % (HASHSIZE-2));
 else if(choice==2)
   index2= 5-(index % 7);
 else if(choice==3)
   index2= (6-(index % 6));       //h(k,i) = (h1(k) + i.h2(k))mod m

 do              		 //probe loop
 {
  index=(index1 + (i*index2)) % HASHSIZE;
  i++;
 }while((hashtable[index].user!=NULL)&&(i<5));

 return index;
}

//search in hashtable
int htable_search(node *hashtable,char *str)
{
 int index=0,index1=0,index2=0,i=0,flag=0,len=0;
 char *tmp=NULL;
 node *target;
 len=strlen(str);
 tmp=(char*)malloc((len+1)*(sizeof(char)));
 strcpy(tmp,str);
 
 while(*tmp)
 {
  index+=*tmp;
  tmp++;
 }

 				//diffrent hash functions used
 index1=(index % HASHSIZE);
 if(choice==1)
   index2=(index % (HASHSIZE-2));
 else if(choice==2)
   index2= 5-(index % 7);
 else if(choice==3)
   index2= (6-(index % 6));       //h(k,i) = (h1(k) + i.h2(k))mod m
 printf("\n");
 
 do              		 //probe loop
 {
  index=(index1 + (i*index2)) % HASHSIZE; 
  i++;
   
  target= hashtable + index;
  
  if(target->user!=NULL)
  {
   if(strcmp(target->user,str)==0)
   {
    flag=1;
    break;
   }
  }
 }while((flag==0)&&(i<HASHSIZE));

 if(flag==1)
 {
  return index;
 }
 else
 {
  return (-1);
 }
}

// display hashtable
void htable_display(node *hashtable)
{
 int i=0;
 node *target;
 
 printf("\n\nHASH TABLE IS...\n");
 for(i=0;i<HASHSIZE;i++)
 {
  if(hashtable[i].user != NULL)
  {
   printf("\n");
   target = hashtable+i;
   while(target)
   { 
    printf("      %s", target->user);
    target=target->next;
   }	//while close
  }     //if close
 }      //for close
}
